﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ShaHashChecker.GUI
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        private void plainText_TextChanged(object sender, EventArgs e)
        {
            var hashedText = HashHelper.GetHashString(plainText.Text);

            generatedHash.Text = hashedText;

            UpdatePaddedHash();

            searchButton.Enabled = IsReadyToSearch();
        }

        private bool IsReadyToSearch()
        {
            return !string.IsNullOrEmpty(plainText.Text) && !string.IsNullOrEmpty(hashListFileName.Text) && File.Exists(hashListFileName.Text);
        }

        private void UpdatePaddedHash()
        {
            if (shouldPad.Checked)
            {
                var pad = (int) padUpDown.Value;
                paddedHash.Text = new string('0', pad) + generatedHash.Text.Substring(pad);
            }
            else
            {
                paddedHash.Text = string.Empty;
            }
        }

        private void isPassword_CheckedChanged(object sender, EventArgs e)
        {
            plainText.UseSystemPasswordChar = isPassword.Checked;
        }

        private void shouldPad_CheckedChanged(object sender, EventArgs e)
        {
            padUpDown.Enabled = shouldPad.Checked;
            UpdatePaddedHash();
        }

        private void hashBrowseButton_Click(object sender, EventArgs e)
        {
            var result = openFileDialog1.ShowDialog(this);

            if (result == DialogResult.OK && openFileDialog1.CheckFileExists)
            {
                hashListFileName.Text = openFileDialog1.FileName;
            }
        }

        private void padUpDown_ValueChanged(object sender, EventArgs e)
        {
            UpdatePaddedHash();
        }

        private bool CheckHash()
        {
            var fileName = hashListFileName.Text;
            var hashes = shouldPad.Checked ? 
                new[] {generatedHash.Text.ToLower(), paddedHash.Text.ToLower()} : new []{generatedHash.Text.ToLower()};

            if (!File.Exists(fileName))
            {
                throw new FileNotFoundException("File not found. Make sure you got it right and try again.");
            }

            Debug.Assert(File.Exists(fileName));

            var lineCounter = 0;
            var linesPercent = 0;
            using (var textStreamReader = new StreamReader(fileName))
            {
                var fileSize = new FileInfo(fileName).Length / 42;
                while (textStreamReader.Peek() > 0)
                {
                    var hashInFile = textStreamReader.ReadLine().ToLower();
                    if (hashes.Contains(hashInFile))
                    {
                        return true;
                    }
                    lineCounter++;

                    if (100 * lineCounter / fileSize <= linesPercent) continue;

                    linesPercent++;

                    searchProgressBar.Value = linesPercent;
                }
                searchProgressBar.Value = 100;
            }
            return false;
        }

        private void searchButton_Click(object sender, EventArgs e)
        {
            found.Visible = false;
            notFound.Visible = false;
            try
            {
                var hashFound = CheckHash();

                found.Visible = hashFound;
                notFound.Visible = !hashFound;
            }
            catch (FileNotFoundException ex)
            {
                MessageBox.Show(ex.Message);
            }
            catch (Exception)
            {
                MessageBox.Show("Error reading file. Make sure that it is a text file containing SHA-1 hashes.");
            }
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            plainText.UseSystemPasswordChar = isPassword.Checked;

            padUpDown.Enabled = shouldPad.Checked;


        }

        private void hashListFileName_TextChanged(object sender, EventArgs e)
        {
            var fileExists = File.Exists(hashListFileName.Text);

            searchButton.Enabled = IsReadyToSearch();

            fileNotFoundLabel.Visible = !string.IsNullOrEmpty(hashListFileName.Text) && !fileExists;
        }
    }
}
